<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
<title>work.md</title><link href='http://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext' rel='stylesheet' type='text/css' /><style type='text/css'>html {overflow-x: initial !important;}.CodeMirror { height: auto; }
.CodeMirror-scroll { overflow-y: hidden; overflow-x: auto; }
.CodeMirror-lines { padding: 4px 0px; }
.CodeMirror pre { }
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { background-color: white; }
.CodeMirror-gutters { border-right: 1px solid rgb(221, 221, 221); background-color: rgb(247, 247, 247); white-space: nowrap; }
.CodeMirror-linenumbers { }
.CodeMirror-linenumber { padding: 0px 3px 0px 5px; text-align: right; color: rgb(153, 153, 153); }
.CodeMirror div.CodeMirror-cursor { border-left: 1px solid black; z-index: 3; }
.CodeMirror div.CodeMirror-secondarycursor { border-left: 1px solid silver; }
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { width: auto; border: 0px; background: rgb(119, 238, 119); z-index: 1; }
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite { }
.cm-tab { display: inline-block; }
.cm-s-typora-default .cm-header, .cm-s-typora-default .cm-property { color: rgb(217, 79, 138); }
.cm-s-typora-default pre.cm-header1:not(.cm-atom) :not(.cm-overlay) { font-size: 2rem; line-height: 2rem; }
.cm-s-typora-default pre.cm-header2:not(.cm-atom) :not(.cm-overlay) { font-size: 1.4rem; line-height: 1.4rem; }
.cm-s-typora-default .cm-atom, .cm-s-typora-default .cm-number { color: rgb(149, 132, 134); }
.cm-s-typora-default .cm-table-row, .cm-s-typora-default .cm-block-start { font-family: monospace; }
.cm-s-typora-default .cm-comment, .cm-s-typora-default .cm-code { color: rgb(74, 90, 159); font-family: monospace; }
.cm-s-typora-default .cm-tag { color: rgb(169, 68, 66); }
.cm-s-typora-default .cm-string { color: rgb(126, 134, 169); }
.cm-s-typora-default .cm-link { color: rgb(196, 122, 15); text-decoration: underline; }
.cm-s-typora-default .cm-variable-2, .cm-s-typora-default .cm-variable-1 { color: inherit; }
.cm-s-typora-default .cm-overlay { font-size: 1rem; font-family: monospace; }
.CodeMirror.cm-s-typora-default div.CodeMirror-cursor { border-left: 3px solid rgb(228, 98, 154); }
.cm-s-typora-default .CodeMirror-activeline-background { left: -60px; right: -30px; background: rgba(204, 204, 204, 0.2); }
.cm-s-typora-default .CodeMirror-gutters { border-right: none; background-color: inherit; }
.cm-s-typora-default .cm-trailing-space-new-line::after, .cm-startspace::after, .cm-starttab .cm-tab::after { content: "•"; position: absolute; left: 0px; opacity: 0; font-family: LetterGothicStd, monospace; }
.os-windows .cm-startspace::after, .os-windows .cm-starttab .cm-tab::after { left: -0.1em; }
.cm-starttab .cm-tab::after { content: " "; }
.cm-startspace, .cm-tab, .cm-starttab, .cm-trailing-space-a, .cm-trailing-space-b, .cm-trailing-space-new-line { font-family: monospace; position: relative; }
.cm-s-typora-default .cm-trailing-space-new-line::after { content: "↓"; opacity: 0.3; }
.cm-s-inner .cm-keyword { color: rgb(119, 0, 136); }
.cm-s-inner .cm-atom, .cm-s-inner.cm-atom { color: rgb(34, 17, 153); }
.cm-s-inner .cm-number { color: rgb(17, 102, 68); }
.cm-s-inner .cm-def { color: rgb(0, 0, 255); }
.cm-s-inner .cm-variable { color: black; }
.cm-s-inner .cm-variable-2 { color: rgb(0, 85, 170); }
.cm-s-inner .cm-variable-3 { color: rgb(0, 136, 85); }
.cm-s-inner .cm-property { color: black; }
.cm-s-inner .cm-operator { color: rgb(152, 26, 26); }
.cm-s-inner .cm-comment, .cm-s-inner.cm-comment { color: rgb(170, 85, 0); }
.cm-s-inner .cm-string { color: rgb(170, 17, 17); }
.cm-s-inner .cm-string-2 { color: rgb(255, 85, 0); }
.cm-s-inner .cm-meta { color: rgb(85, 85, 85); }
.cm-s-inner .cm-qualifier { color: rgb(85, 85, 85); }
.cm-s-inner .cm-builtin { color: rgb(51, 0, 170); }
.cm-s-inner .cm-bracket { color: rgb(153, 153, 119); }
.cm-s-inner .cm-tag { color: rgb(17, 119, 0); }
.cm-s-inner .cm-attribute { color: rgb(0, 0, 204); }
.cm-s-inner .cm-header, .cm-s-inner.cm-header { color: blue; }
.cm-s-inner .cm-quote, .cm-s-inner.cm-quote { color: rgb(0, 153, 0); }
.cm-s-inner .cm-hr, .cm-s-inner.cm-hr { color: rgb(153, 153, 153); }
.cm-s-inner .cm-link, .cm-s-inner.cm-link { color: rgb(0, 0, 204); }
.cm-negative { color: rgb(221, 68, 68); }
.cm-positive { color: rgb(34, 153, 34); }
.cm-header, .cm-strong { font-weight: bold; }
.cm-del { text-decoration: line-through; }
.cm-em { font-style: italic; }
.cm-link { text-decoration: underline; }
.cm-error { color: rgb(255, 0, 0); }
.cm-invalidchar { color: rgb(255, 0, 0); }
.cm-constant { color: rgb(38, 139, 210); }
.cm-defined { color: rgb(181, 137, 0); }
div.CodeMirror span.CodeMirror-matchingbracket { color: rgb(0, 255, 0); }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: rgb(255, 34, 34); }
.cm-s-inner .CodeMirror-activeline-background { background: inherit; }
.CodeMirror { position: relative; overflow: hidden; }
.CodeMirror-scroll { margin-bottom: -30px; margin-right: -30px; padding-bottom: 30px; padding-right: 30px; height: 100%; outline: none; position: relative; box-sizing: content-box; }
.CodeMirror-sizer { position: relative; }
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none; }
.CodeMirror-vscrollbar { right: 0px; top: 0px; overflow-x: hidden; overflow-y: scroll; }
.CodeMirror-hscrollbar { bottom: 0px; left: 0px; overflow-y: hidden; overflow-x: scroll; }
.CodeMirror-scrollbar-filler { right: 0px; bottom: 0px; }
.CodeMirror-gutter-filler { left: 0px; bottom: 0px; }
.CodeMirror-gutters { position: absolute; left: 0px; top: 0px; padding-bottom: 30px; z-index: 3; }
.CodeMirror-gutter { white-space: normal; height: 100%; box-sizing: content-box; padding-bottom: 30px; margin-bottom: -32px; display: inline-block; }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; }
.CodeMirror-lines { cursor: text; }
.CodeMirror pre { border-radius: 0px; border-width: 0px; background: transparent; font-family: inherit; font-size: inherit; margin: 0px; white-space: pre; word-wrap: normal; color: inherit; z-index: 2; position: relative; overflow: visible; }
.CodeMirror-wrap pre { word-wrap: break-word; white-space: pre-wrap; word-break: normal; }
.CodeMirror-code pre { border-right: 30px solid transparent; width: fit-content; }
.CodeMirror-wrap .CodeMirror-code pre { border-right: none; width: auto; }
.CodeMirror-linebackground { position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 0; }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; }
.CodeMirror-widget { }
.CodeMirror-wrap .CodeMirror-scroll { overflow-x: hidden; }
.CodeMirror-measure { position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden; }
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor { position: absolute; visibility: hidden; border-right: none; width: 0px; }
.CodeMirror div.CodeMirror-cursor { visibility: hidden; }
.CodeMirror-focused div.CodeMirror-cursor { visibility: inherit; }
.CodeMirror-selected { background: rgb(217, 217, 217); }
.CodeMirror-focused .CodeMirror-selected { background: rgb(215, 212, 240); }
.cm-searching { background: rgba(255, 255, 0, 0.4); }
.CodeMirror span { }
@media print {
  .CodeMirror div.CodeMirror-cursor { visibility: hidden; }
}
.CodeMirror-lint-markers { width: 16px; }
.CodeMirror-lint-tooltip { background-color: infobackground; border: 1px solid black; border-radius: 4px; color: infotext; font-family: monospace; overflow: hidden; padding: 2px 5px; position: fixed; white-space: pre-wrap; z-index: 10000; max-width: 600px; opacity: 0; transition: opacity 0.4s; font-size: 0.8em; }
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning { background-position: left bottom; background-repeat: repeat-x; }
.CodeMirror-lint-mark-error { background-image: url(""); }
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning { background-position: center center; background-repeat: no-repeat; cursor: pointer; display: inline-block; height: 16px; width: 16px; vertical-align: middle; position: relative; }
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { padding-left: 18px; background-position: left top; background-repeat: no-repeat; }
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error { background-image: url(""); }
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { background-image: url(""); }
.CodeMirror-lint-marker-multiple { background-image: url(""); background-repeat: no-repeat; background-position: right bottom; width: 100%; height: 100%; }


html { font-size: 14px; background-color: rgb(255, 255, 255); color: rgb(51, 51, 51); }
body { margin: 0px; padding: 0px; height: auto; bottom: 0px; top: 0px; left: 0px; right: 0px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1rem; line-height: 1.42857; overflow-x: hidden; background: inherit; }
a:active, a:hover { outline: 0px; }
.in-text-selection, ::selection { background: rgb(181, 214, 252); text-shadow: none; }
#write { margin: 0px auto; height: auto; width: inherit; word-break: normal; word-wrap: break-word; position: relative; padding-bottom: 70px; white-space: pre-wrap; overflow-x: visible; }
.for-image #write { padding-left: 8px; padding-right: 8px; }
body.typora-export { padding-left: 30px; padding-right: 30px; }
@media screen and (max-width: 500px) {
  body.typora-export { padding-left: 0px; padding-right: 0px; }
  .CodeMirror-sizer { margin-left: 0px !important; }
  .CodeMirror-gutters { display: none !important; }
}
.typora-export #write { margin: 0px auto; }
#write > p:first-child, #write > ul:first-child, #write > ol:first-child, #write > pre:first-child, #write > blockquote:first-child, #write > div:first-child, #write > table:first-child { margin-top: 30px; }
#write li > table:first-child { margin-top: -20px; }
img { max-width: 100%; vertical-align: middle; }
input, button, select, textarea { color: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
::before, ::after, * { box-sizing: border-box; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write div, #write pre { width: inherit; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6 { position: relative; }
h1 { font-size: 2rem; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.6rem; }
h4 { font-size: 1.4rem; }
h5 { font-size: 1.2rem; }
h6 { font-size: 1rem; }
p { -webkit-margin-before: 1rem; -webkit-margin-after: 1rem; -webkit-margin-start: 0px; -webkit-margin-end: 0px; }
.mathjax-block { margin-top: 0px; margin-bottom: 0px; -webkit-margin-before: 0rem; -webkit-margin-after: 0rem; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: bold; font-style: italic; }
a { cursor: pointer; }
sup.md-footnote { padding: 2px 4px; background-color: rgba(238, 238, 238, 0.701961); color: rgb(85, 85, 85); border-radius: 4px; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; margin: 4px 0px 0px; }
tr { break-inside: avoid; break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; break-inside: auto; text-align: left; }
table.md-table td { min-width: 80px; }
.CodeMirror-gutters { border-right: 0px; background-color: inherit; }
.CodeMirror { text-align: left; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
pre { white-space: pre-wrap; }
.CodeMirror-gutters { margin-right: 4px; }
.md-fences { font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; overflow: visible; white-space: pre; background: inherit; position: relative !important; }
.md-diagram-panel { width: 100%; margin-top: 10px; text-align: center; padding-top: 0px; padding-bottom: 8px; overflow-x: auto; }
.md-fences .CodeMirror.CodeMirror-wrap { top: -1.6em; margin-bottom: -1.6em; }
.md-fences.mock-cm { white-space: pre-wrap; }
.show-fences-line-number .md-fences { padding-left: 0px; }
.show-fences-line-number .md-fences.mock-cm { padding-left: 40px; }
.footnotes { opacity: 0.8; font-size: 0.9rem; padding-top: 1em; padding-bottom: 1em; }
.footnotes + .footnotes { margin-top: -1em; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; background: transparent; text-decoration: none; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; -webkit-tap-highlight-color: transparent; line-height: normal; font-weight: normal; text-align: left; box-sizing: content-box; direction: ltr; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li p, li .mathjax-block { margin: 0.5rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; }
@media print {
  html, body { height: 100%; }
  .typora-export * { -webkit-print-color-adjust: exact; }
  h1, h2, h3, h4, h5, h6 { break-after: avoid-page; orphans: 2; }
  p { orphans: 4; }
  html.blink-to-pdf { font-size: 13px; }
  .typora-export #write { padding-left: 1cm; padding-right: 1cm; }
  .typora-export #write::after { height: 0px; }
  @page { margin: 20mm 0mm; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
pre.md-meta-block { font-size: 0.8rem; min-height: 2.86rem; white-space: pre-wrap; background: rgb(204, 204, 204); display: block; overflow-x: hidden; }
p .md-image:only-child { display: inline-block; width: 100%; text-align: center; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.mathjax-block { white-space: pre; overflow: hidden; width: 100%; }
p + .mathjax-block { margin-top: -1.143rem; }
.mathjax-block:not(:empty)::after { display: none; }
[contenteditable="true"]:active, [contenteditable="true"]:focus { outline: none; box-shadow: none; }
.task-list { list-style-type: none; }
.task-list-item { position: relative; padding-left: 1em; }
.task-list-item input { position: absolute; top: 0px; left: 0px; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc::after, .md-toc-content::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); text-decoration: none; }
.md-toc-inner:hover { }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: bold; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
@media screen and (max-width: 48em) {
  .md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
  .md-toc-h4 .md-toc-inner { margin-left: 5em; }
  .md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
  .md-toc-h6 .md-toc-inner { margin-left: 8em; }
}
a.md-toc-inner { font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: "."; }
.md-tag { opacity: 0.5; }
.md-comment { color: rgb(162, 127, 3); opacity: 0.8; font-family: monospace; }
code { text-align: left; }
h1 .md-tag, h2 .md-tag, h3 .md-tag, h4 .md-tag, h5 .md-tag, h6 .md-tag { font-weight: initial; opacity: 0.35; }
a.md-print-anchor { border-width: initial !important; border-style: none !important; border-color: initial !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: none !important; background: transparent !important; text-decoration: initial !important; text-shadow: initial !important; }
.md-inline-math .MathJax_SVG .noError { display: none !important; }
.mathjax-block .MathJax_SVG_Display { text-align: center; margin: 1em 0em; position: relative; text-indent: 0px; max-width: none; max-height: none; min-height: 0px; min-width: 100%; width: auto; display: block !important; }
.MathJax_SVG_Display, .md-inline-math .MathJax_SVG_Display { width: auto; margin: inherit; display: inline-block !important; }
.MathJax_SVG .MJX-monospace { font-family: monospace; }
.MathJax_SVG .MJX-sans-serif { font-family: sans-serif; }
.MathJax_SVG { display: inline; font-style: normal; font-weight: normal; line-height: normal; zoom: 90%; text-indent: 0px; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; padding: 0px; margin: 0px; }
.MathJax_SVG * { transition: none; }


@include-when-export url(http://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext);

/**
 * css forked from https://github.com/GitbookIO/gitbook 
 * www.gitbook.com
 * Apache License
 * https://github.com/GitbookIO/gitbook/blob/master/LICENSE
 **/

@font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: normal;
    src: local('Open Sans Regular'),url('file:///C:%5CUsers%5Csevn%5CAppData%5CRoaming%5CTypora%5Cthemes%5Cgithub%5C400.woff') format('woff')
}

@font-face {
    font-family: 'Open Sans';
    font-style: italic;
    font-weight: normal;
    src: local('Open Sans Italic'),url('file:///C:%5CUsers%5Csevn%5CAppData%5CRoaming%5CTypora%5Cthemes%5Cgithub%5C400i.woff') format('woff')
}

@font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: bold;
    src: local('Open Sans Bold'),url('file:///C:%5CUsers%5Csevn%5CAppData%5CRoaming%5CTypora%5Cthemes%5Cgithub%5C700.woff') format('woff')
}

@font-face {
    font-family: 'Open Sans';
    font-style: italic;
    font-weight: bold;
    src: local('Open Sans Bold Italic'),url('file:///C:%5CUsers%5Csevn%5CAppData%5CRoaming%5CTypora%5Cthemes%5Cgithub%5C700i.woff') format('woff')
}

html {
    font-size: 16px;
}

body {
    font-family: "Open Sans","Clear Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
    color: rgb(51, 51, 51);
    line-height: 1.6;
}

#write{
    max-width: 860px;
  	margin: 0 auto;
  	padding: 20px 30px 40px 30px;
	padding-top: 20px;
    padding-bottom: 100px;
}
#write > ul:first-child,
#write > ol:first-child{
    margin-top: 30px;
}

body > *:first-child {
    margin-top: 0 !important;
}
body > *:last-child {
    margin-bottom: 0 !important;
}
a {
    color: #4183C4;
}
h1,
h2,
h3,
h4,
h5,
h6 {
    position: relative;
    margin-top: 1rem;
    margin-bottom: 1rem;
    font-weight: bold;
    line-height: 1.4;
    cursor: text;
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
    /*background: url("file:///C:%5CUsers%5Csevn%5CAppData%5CRoaming%5Cimages%5Cmodules%5Cstyleguide%5Cpara.png") no-repeat 10px center;*/
    text-decoration: none;
}
h1 tt,
h1 code {
    font-size: inherit;
}
h2 tt,
h2 code {
    font-size: inherit;
}
h3 tt,
h3 code {
    font-size: inherit;
}
h4 tt,
h4 code {
    font-size: inherit;
}
h5 tt,
h5 code {
    font-size: inherit;
}
h6 tt,
h6 code {
    font-size: inherit;
}
h1 {
    padding-bottom: .3em;
    font-size: 2.25em;
    line-height: 1.2;
    border-bottom: 1px solid #eee;
}
h2 {
   padding-bottom: .3em;
    font-size: 1.75em;
    line-height: 1.225;
    border-bottom: 1px solid #eee;
}
h3 {
    font-size: 1.5em;
    line-height: 1.43;
}
h4 {
    font-size: 1.25em;
}
h5 {
    font-size: 1em;
}
h6 {
   font-size: 1em;
    color: #777;
}
p,
blockquote,
ul,
ol,
dl,
table{
    margin: 0.8em 0;
}
li>ol,
li>ul {
    margin: 0 0;
}
hr {
    height: 4px;
    padding: 0;
    margin: 16px 0;
    background-color: #e7e7e7;
    border: 0 none;
    overflow: hidden;
    box-sizing: content-box;
    border-bottom: 1px solid #ddd;
}

body > h2:first-child {
    margin-top: 0;
    padding-top: 0;
}
body > h1:first-child {
    margin-top: 0;
    padding-top: 0;
}
body > h1:first-child + h2 {
    margin-top: 0;
    padding-top: 0;
}
body > h3:first-child,
body > h4:first-child,
body > h5:first-child,
body > h6:first-child {
    margin-top: 0;
    padding-top: 0;
}
a:first-child h1,
a:first-child h2,
a:first-child h3,
a:first-child h4,
a:first-child h5,
a:first-child h6 {
    margin-top: 0;
    padding-top: 0;
}
h1 p,
h2 p,
h3 p,
h4 p,
h5 p,
h6 p {
    margin-top: 0;
}
li p.first {
    display: inline-block;
}
ul,
ol {
    padding-left: 30px;
}
ul:first-child,
ol:first-child {
    margin-top: 0;
}
ul:last-child,
ol:last-child {
    margin-bottom: 0;
}
blockquote {
    border-left: 4px solid #dddddd;
    padding: 0 15px;
    color: #777777;
}
blockquote blockquote {
    padding-right: 0;
}
table {
    padding: 0;
    word-break: initial;
}
table tr {
    border-top: 1px solid #cccccc;
    background-color: white;
    margin: 0;
    padding: 0;
}
table tr:nth-child(2n) {
    background-color: #f8f8f8;
}
table tr th {
    font-weight: bold;
    border: 1px solid #cccccc;
    text-align: left;
    margin: 0;
    padding: 6px 13px;
}
table tr td {
    border: 1px solid #cccccc;
    text-align: left;
    margin: 0;
    padding: 6px 13px;
}
table tr th:first-child,
table tr td:first-child {
    margin-top: 0;
}
table tr th:last-child,
table tr td:last-child {
    margin-bottom: 0;
}

.CodeMirror-gutters {
    border-right: 1px solid #ddd;
}

.md-fences,
code,
tt {
    border: 1px solid #ddd;
    background-color: #f8f8f8;
    border-radius: 3px;
    padding: 0;
    font-family: Consolas, "Liberation Mono", Courier, monospace;
    padding: 2px 4px 0px 4px;
    font-size: 0.9em;
}

.md-fences {
    margin-bottom: 15px;
    margin-top: 15px;
    padding: 0.2em 1em;
    padding-top: 8px;
    padding-bottom: 6px;
}
.task-list{
	padding-left: 0;
}

.task-list-item {
	padding-left:32px;
}

.task-list-item input {
  top: 3px;
  left: 8px;
}

@media screen and (min-width: 914px) {
    /*body {
        width: 854px;
        margin: 0 auto;
    }*/
}
@media print {
    html {
        font-size: 13px;
    }
    table,
    pre {
        page-break-inside: avoid;
    }
    pre {
        word-wrap: break-word;
    }
}

.md-fences {
	background-color: #f8f8f8;
}
#write pre.md-meta-block {
	padding: 1rem;
    font-size: 85%;
    line-height: 1.45;
    background-color: #f7f7f7;
    border: 0;
    border-radius: 3px;
    color: #777777;
    margin-top: 0 !important;
}

.mathjax-block>.code-tooltip {
	bottom: .375rem;
}

#write>h3.md-focus:before{
	left: -1.5625rem;
	top: .375rem;
}
#write>h4.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
#write>h5.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
#write>h6.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
.md-image>.md-meta {
    border: 1px solid #ddd;
    border-radius: 3px;
    font-family: Consolas, "Liberation Mono", Courier, monospace;
    padding: 2px 4px 0px 4px;
    font-size: 0.9em;
    color: inherit;
}

.md-tag{
	color: inherit;
}

.md-toc { 
    margin-top:20px;
    padding-bottom:20px;
}

#typora-quick-open {
    border: 1px solid #ddd;
    background-color: #f8f8f8;
}

#typora-quick-open-item {
    background-color: #FAFAFA;
    border-color: #FEFEFE #e5e5e5 #e5e5e5 #eee;
    border-style: solid;
    border-width: 1px;
}

#md-notification:before {
    top: 10px;
}

/** focus mode */
.on-focus-mode blockquote {
    border-left-color: rgba(85, 85, 85, 0.12);
}

header, .context-menu, .megamenu-content, footer{
    font-family: "Segoe UI", "Arial", sans-serif;
}


</style>
</head>
<body class='typora-export' >
<div  id='write'  class = 'is-node'><div class='md-toc' mdtype='toc'><p class="md-toc-content"><span class="md-toc-item md-toc-h2" data-ref="n5"><a class="md-toc-inner" href="#header-n5">自我介绍</a></span><span class="md-toc-item md-toc-h2" data-ref="n7"><a class="md-toc-inner" href="#header-n7">介绍一下项目，以及难点亮点</a></span><span class="md-toc-item md-toc-h2" data-ref="n10"><a class="md-toc-inner" href="#header-n10">科研项目</a></span><span class="md-toc-item md-toc-h2" data-ref="n17"><a class="md-toc-inner" href="#header-n17">Java 集合</a></span><span class="md-toc-item md-toc-h3" data-ref="n20"><a class="md-toc-inner" href="#header-n20">各种集合的简介及区别联系</a></span><span class="md-toc-item md-toc-h3" data-ref="n54"><a class="md-toc-inner" href="#header-n54">HashMap多线程下出现的问题</a></span><span class="md-toc-item md-toc-h3" data-ref="n62"><a class="md-toc-inner" href="#header-n62">ConcurrentHashMap 如何扩容？</a></span><span class="md-toc-item md-toc-h2" data-ref="n63"><a class="md-toc-inner" href="#header-n63">Java NIO</a></span><span class="md-toc-item md-toc-h3" data-ref="n73"><a class="md-toc-inner" href="#header-n73">Buffer</a></span><span class="md-toc-item md-toc-h3" data-ref="n78"><a class="md-toc-inner" href="#header-n78">Channel</a></span><span class="md-toc-item md-toc-h3" data-ref="n87"><a class="md-toc-inner" href="#header-n87">Selector</a></span><span class="md-toc-item md-toc-h2" data-ref="n113"><a class="md-toc-inner" href="#header-n113">SpringMVC和MyBatis</a></span><span class="md-toc-item md-toc-h3" data-ref="n114"><a class="md-toc-inner" href="#header-n114">SpringMVC</a></span><span class="md-toc-item md-toc-h4" data-ref="n115"><a class="md-toc-inner" href="#header-n115">运行流程</a></span><span class="md-toc-item md-toc-h3" data-ref="n118"><a class="md-toc-inner" href="#header-n118">MyBatis</a></span><span class="md-toc-item md-toc-h4" data-ref="n119"><a class="md-toc-inner" href="#header-n119">简介</a></span><span class="md-toc-item md-toc-h4" data-ref="n122"><a class="md-toc-inner" href="#header-n122">动态代理</a></span><span class="md-toc-item md-toc-h4" data-ref="n125"><a class="md-toc-inner" href="#header-n125">常用标签</a></span><span class="md-toc-item md-toc-h4" data-ref="n133"><a class="md-toc-inner" href="#header-n133">动态SQL</a></span><span class="md-toc-item md-toc-h4" data-ref="n136"><a class="md-toc-inner" href="#header-n136">事务支持和缓存机制</a></span><span class="md-toc-item md-toc-h2" data-ref="n151"><a class="md-toc-inner" href="#header-n151">垃圾回收机制</a></span><span class="md-toc-item md-toc-h2" data-ref="n174"><a class="md-toc-inner" href="#header-n174">类加载机制</a></span><span class="md-toc-item md-toc-h2" data-ref="n179"><a class="md-toc-inner" href="#header-n179">多线程，并发</a></span><span class="md-toc-item md-toc-h3" data-ref="n180"><a class="md-toc-inner" href="#header-n180">volatile</a></span><span class="md-toc-item md-toc-h3" data-ref="n183"><a class="md-toc-inner" href="#header-n183">信号量 (Semaphore) ['seməfɔː]</a></span><span class="md-toc-item md-toc-h3" data-ref="n186"><a class="md-toc-inner" href="#header-n186">AtomicInteger</a></span><span class="md-toc-item md-toc-h3" data-ref="n189"><a class="md-toc-inner" href="#header-n189">ThreadLocal</a></span><span class="md-toc-item md-toc-h3" data-ref="n192"><a class="md-toc-inner" href="#header-n192">Future</a></span><span class="md-toc-item md-toc-h3" data-ref="n195"><a class="md-toc-inner" href="#header-n195">final 域</a></span><span class="md-toc-item md-toc-h3" data-ref="n198"><a class="md-toc-inner" href="#header-n198">获取线程dump文件</a></span><span class="md-toc-item md-toc-h3" data-ref="n201"><a class="md-toc-inner" href="#header-n201">线程的唤醒与阻塞</a></span><span class="md-toc-item md-toc-h3" data-ref="n215"><a class="md-toc-inner" href="#header-n215">线程池</a></span><span class="md-toc-item md-toc-h4" data-ref="n216"><a class="md-toc-inner" href="#header-n216">简介</a></span><span class="md-toc-item md-toc-h4" data-ref="n219"><a class="md-toc-inner" href="#header-n219">如果你提交任务时，线程池队列已满，这时会发生什么</a></span><span class="md-toc-item md-toc-h3" data-ref="n227"><a class="md-toc-inner" href="#header-n227">几种锁</a></span><span class="md-toc-item md-toc-h3" data-ref="n241"><a class="md-toc-inner" href="#header-n241">如何在两个线程之间共享数据</a></span><span class="md-toc-item md-toc-h2" data-ref="n244"><a class="md-toc-inner" href="#header-n244">http 和 https</a></span><span class="md-toc-item md-toc-h2" data-ref="n252"><a class="md-toc-inner" href="#header-n252">数据库</a></span><span class="md-toc-item md-toc-h3" data-ref="n253"><a class="md-toc-inner" href="#header-n253">mysql为什么用B+树</a></span><span class="md-toc-item md-toc-h3" data-ref="n256"><a class="md-toc-inner" href="#header-n256">数据库事务的四种隔离级别</a></span><span class="md-toc-item md-toc-h3" data-ref="n270"><a class="md-toc-inner" href="#header-n270">ACID事务</a></span><span class="md-toc-item md-toc-h3" data-ref="n284"><a class="md-toc-inner" href="#header-n284">InnoDB和MyISAM</a></span><span class="md-toc-item md-toc-h4" data-ref="n285"><a class="md-toc-inner" href="#header-n285">InnoDB</a></span><span class="md-toc-item md-toc-h4" data-ref="n300"><a class="md-toc-inner" href="#header-n300">MyISAM</a></span><span class="md-toc-item md-toc-h4" data-ref="n311"><a class="md-toc-inner" href="#header-n311">比较和讨论</a></span><span class="md-toc-item md-toc-h2" data-ref="n323"><a class="md-toc-inner" href="#header-n323">设计模式</a></span><span class="md-toc-item md-toc-h3" data-ref="n324"><a class="md-toc-inner" href="#header-n324">几种单例模式</a></span></p></div><h2><a name='header-n5' class='md-header-anchor '></a>自我介绍</h2><p>面试官好，我叫孙浩然，本科毕业于南京信息工程大学网络工程专业，研究生就读于南京航空航天大学软件工程专业。在校期间我努力学习专业知识，本科期间连续四年获得学校奖学金，研究生阶段也已经连续两年获得了研究生一等奖学金，通过了大学英语6级。除了学习，我也比较注重参与实践，比如本科阶段参与到江苏省其向现代化进程监测平台的开发，这是一个基于SpringMVC和MyBatis的Java Web系统；研究生阶段我参与了国家自然科学基金课题，不确定高维多目标优化算法研究和应用，目前已有一篇影响因子3.3的SCI论文在第二次审稿中，今年在该领域权威的国际会议IEEE演化计算大会举办的算法竞赛中，我所设计的算法也是拿到了其中一个竞赛单元的冠军。此外，2015年我还进入焦点科技股份有限公司进行了两个多月的实习，在企业中我也是学到了很多学校中没有学到的知识，比如对java知识更加偏向工程实践的学习，比较系统的学习使用了SpringMVC和MyBatis等开源框架，Maven、Git等团队开发工具的使用以及更加规范的编码习惯。谢谢面试官，我的介绍完了。</p><h2><a name='header-n7' class='md-header-anchor '></a>介绍一下项目，以及难点亮点</h2><p>江苏省气象局现代化进程检测平台。
是江苏省气象局为了统计每个时段气象现代化进程的完成度所做的一个JavaWeb系统。
主要先从省局制定这个年度或者这个时段的评价指标，然后交由市县区去做数据采集，市局审批县区级的数据，省局审批市局的数据。省局在审批的同时，能够看到事实的数据展示。展示时间维度上的变化，地区维度上的变化。
系统主要采用Spring + SpringMVC + MyBatis + velocity实现。前端使用 bootstrap + echarts 实现。
主要的难点在于，对方的需求要求评价指标是可以变化的，比如有一些指标在上一个时段完成了，下一个时段的计划就不需要这个指标，或者省局的一些专家又有新的指标要加进评价计划，这些指标有层级关系。这就要求定制化比较高。这里把指标存入数据库中实现可定制化。即是，指标是可以由用户自己定义的，在制定每个计划时，将这些指标添加到相应的评价体系当中去，并设置相应的权重，评价体系和指标之间是多对多的关系。在录入数据时，要先对评价体系--指标表进行查询，查询到该评价体系所需要的指标（包括权重，目标值），然后进行填写收集的数据。这样一来整个系统比较灵活</p><h2><a name='header-n10' class='md-header-anchor '></a>科研项目</h2><p>主要用遗传算法解决多目标优化问题。相对于单目标优化问题，多目标优化问题有一个解集。我们需要解决的是能让最终得到的解更加接近真实的最优解集，并在最优解集上展开。由于遗传算法每一次迭代都要在<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-1-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="3.226ex" height="2.009ex" viewBox="0 -755.5 1389 865.1" role="img" focusable="false" style="vertical-align: -0.255ex;"><defs><path stroke-width="1" id="E1-MJMAIN-32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"></path><path stroke-width="1" id="E1-MJMATHI-4E" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E1-MJMAIN-32" x="0" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E1-MJMATHI-4E" x="500" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-1">2N</script>个解里选择<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-8-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="2.064ex" height="2.009ex" viewBox="0 -755.5 888.5 865.1" role="img" focusable="false" style="vertical-align: -0.255ex;"><defs><path stroke-width="1" id="E8-MJMATHI-4E" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E8-MJMATHI-4E" x="0" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-8">N</script>个进行下一次的交叉变异生成新解。超多目标优化问题面临的问题在于选择解的时候丧失选择的压力。所以采用了先寻找边界解，再通过边界解确定的范围以选择的方法解决这个问题。边界解由于在某一个小范围内，所以选择压力较大。</p><h2><a name='header-n17' class='md-header-anchor '></a>Java 集合</h2><p>Java 集合在util（[ju til]）包下，主要包括Collection和Map两个接口。Collection又包括Map，List，Quene三个接口。List主要包括ArrayList，LinkedList，Vector等实现类，LinkedList同时实现了Queue接口，Queue中包含了一些封装的操作（add offer || remove poll element peek）。Queue还有一个实现类是PriorityQueue，此类底层使用一个堆实现的，每次都返回最小值/最大值(可以实现Comparator重写compare实现)。此外，还有一个Set接口，Set接口底层实现是根据Map的，采用适配器模式。add方法即Map接口中的put(e,null)。以下介绍下Map接口。
Map接口包含Hashtable、HashMap、LinkedHashMap、TreeMap、ConcurrentHashMap等，TreeMap同时实现了SortedMap，为有序的Map。</p><h3><a name='header-n20' class='md-header-anchor '></a>各种集合的简介及区别联系</h3><ul><li>ArrayList：底层用数组实现，插入，添加，获取的的时间复杂度都为<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-6-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="4.745ex" height="2.634ex" viewBox="0 -809.3 2043 1134.2" role="img" focusable="false" style="vertical-align: -0.755ex;"><defs><path stroke-width="1" id="E6-MJMATHI-4F" d="M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z"></path><path stroke-width="1" id="E6-MJMAIN-28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path><path stroke-width="1" id="E6-MJMAIN-31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path><path stroke-width="1" id="E6-MJMAIN-29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMATHI-4F" x="0" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMAIN-28" x="763" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMAIN-31" x="1153" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMAIN-29" x="1653" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-6">O(1)</script>。删除的时间复杂度为<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-5-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="4.977ex" height="2.634ex" viewBox="0 -809.3 2143 1134.2" role="img" focusable="false" style="vertical-align: -0.755ex;"><defs><path stroke-width="1" id="E5-MJMATHI-4F" d="M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z"></path><path stroke-width="1" id="E5-MJMAIN-28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path><path stroke-width="1" id="E5-MJMATHI-6E" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path><path stroke-width="1" id="E5-MJMAIN-29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMATHI-4F" x="0" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMAIN-28" x="763" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMATHI-6E" x="1153" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMAIN-29" x="1753" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-5">O(n)</script>。有两个标志数据，capacity为容量，size为当前元素的数量。当容量不够扩容时使用Arrays.copyOf进行复制操作，并且容量扩展为原来容量的1.5倍。<code>DEFULT_CAPACITY</code>为10。copyOf 方法调用了System.arraycopy方法，该方法是一个native方法。</li><li>LinkedList：底层用双向链表实现，插入，获取需要<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-5-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="4.977ex" height="2.634ex" viewBox="0 -809.3 2143 1134.2" role="img" focusable="false" style="vertical-align: -0.755ex;"><defs><path stroke-width="1" id="E5-MJMATHI-4F" d="M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z"></path><path stroke-width="1" id="E5-MJMAIN-28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path><path stroke-width="1" id="E5-MJMATHI-6E" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path><path stroke-width="1" id="E5-MJMAIN-29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMATHI-4F" x="0" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMAIN-28" x="763" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMATHI-6E" x="1153" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E5-MJMAIN-29" x="1753" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-5">O(n)</script>时间复杂度，添加、删除需要<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-6-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="4.745ex" height="2.634ex" viewBox="0 -809.3 2043 1134.2" role="img" focusable="false" style="vertical-align: -0.755ex;"><defs><path stroke-width="1" id="E6-MJMATHI-4F" d="M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z"></path><path stroke-width="1" id="E6-MJMAIN-28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path><path stroke-width="1" id="E6-MJMAIN-31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path><path stroke-width="1" id="E6-MJMAIN-29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMATHI-4F" x="0" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMAIN-28" x="763" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMAIN-31" x="1153" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E6-MJMAIN-29" x="1653" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-6">O(1)</script>的时间复杂度。</li><li>Vector：与ArrayList的区别在于Vector是线程安全的，（可以用<code>Collections.sychronizedList()</code>包装ArrayList）单线程情况下效率较低，同时在add操作时，ArrayList扩容为1.5倍，Vector扩容为2倍。</li><li>Hashtable：Hashtable是一个线程安全的类，其方法都是sychronized的。其与HashMap的关系有点像Vector与ArrayList的关系。</li><li>HashMap：其底层为Hash表，（数组和单链表的集合），容量可以被用户指定，默认为1&lt;&lt;4（16）（为2的幂的原因在于之后的hash操作返回index，使用的是&amp;的位运算，以提高效率），负载因子load_factor默认为0.75，当hash表中的元素数量大于总容量的0.75时，就要对hash扩容，扩展为原容量的两倍，并对原来的元素进行重新hash（rehash）。数组叫做bucket（桶），单链表的元素叫做entry（元素）。</li><li>LinkedHashMap与HashMap的不同之处在于使用了双向链表维护了元素之间的插入顺序。即是，插入时既要插入对应的桶中，又要插入到双向链表的尾部。以此保证迭代顺序跟插入顺序相同。</li><li>TreeMap 底层用一个红黑树实现，从而实现了数据的有序。在迭代元素时，按有序的顺序迭代。其插入和获取的时间复杂度均为<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-7-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="7.914ex" height="2.634ex" viewBox="0 -809.3 3407.5 1134.2" role="img" focusable="false" style="vertical-align: -0.755ex;"><defs><path stroke-width="1" id="E7-MJMATHI-4F" d="M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z"></path><path stroke-width="1" id="E7-MJMAIN-28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path><path stroke-width="1" id="E7-MJMATHI-6C" d="M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z"></path><path stroke-width="1" id="E7-MJMATHI-6F" d="M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z"></path><path stroke-width="1" id="E7-MJMATHI-67" d="M311 43Q296 30 267 15T206 0Q143 0 105 45T66 160Q66 265 143 353T314 442Q361 442 401 394L404 398Q406 401 409 404T418 412T431 419T447 422Q461 422 470 413T480 394Q480 379 423 152T363 -80Q345 -134 286 -169T151 -205Q10 -205 10 -137Q10 -111 28 -91T74 -71Q89 -71 102 -80T116 -111Q116 -121 114 -130T107 -144T99 -154T92 -162L90 -164H91Q101 -167 151 -167Q189 -167 211 -155Q234 -144 254 -122T282 -75Q288 -56 298 -13Q311 35 311 43ZM384 328L380 339Q377 350 375 354T369 368T359 382T346 393T328 402T306 405Q262 405 221 352Q191 313 171 233T151 117Q151 38 213 38Q269 38 323 108L331 118L384 328Z"></path><path stroke-width="1" id="E7-MJMATHI-6E" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path><path stroke-width="1" id="E7-MJMAIN-29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E7-MJMATHI-4F" x="0" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E7-MJMAIN-28" x="763" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E7-MJMATHI-6C" x="1153" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E7-MJMATHI-6F" x="1451" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E7-MJMATHI-67" x="1937" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E7-MJMATHI-6E" x="2417" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E7-MJMAIN-29" x="3018" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-7">O(logn)</script>。红黑树的本质是一个2-3查找树，黑链接为2-3查找树中的普通链接，红链接为其中的3节点拆分后的链接，节点的颜色为链接该节点链接的颜色。根节点必须为黑链接，红链接不能连续，大小为<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-8-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="2.064ex" height="2.009ex" viewBox="0 -755.5 888.5 865.1" role="img" focusable="false" style="vertical-align: -0.255ex;"><defs><path stroke-width="1" id="E8-MJMATHI-4E" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E8-MJMATHI-4E" x="0" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-8">N</script>的红黑树高度不会超过<span class="MathJax_Preview"></span><span class="MathJax_SVG" id="MathJax-Element-9-Frame" tabindex="-1" style="font-size: 100%; display: inline-block;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="5.035ex" height="2.384ex" viewBox="0 -755.5 2168 1026.6" role="img" focusable="false" style="vertical-align: -0.63ex;"><defs><path stroke-width="1" id="E9-MJMAIN-32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"></path><path stroke-width="1" id="E9-MJMATHI-6C" d="M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z"></path><path stroke-width="1" id="E9-MJMATHI-67" d="M311 43Q296 30 267 15T206 0Q143 0 105 45T66 160Q66 265 143 353T314 442Q361 442 401 394L404 398Q406 401 409 404T418 412T431 419T447 422Q461 422 470 413T480 394Q480 379 423 152T363 -80Q345 -134 286 -169T151 -205Q10 -205 10 -137Q10 -111 28 -91T74 -71Q89 -71 102 -80T116 -111Q116 -121 114 -130T107 -144T99 -154T92 -162L90 -164H91Q101 -167 151 -167Q189 -167 211 -155Q234 -144 254 -122T282 -75Q288 -56 298 -13Q311 35 311 43ZM384 328L380 339Q377 350 375 354T369 368T359 382T346 393T328 402T306 405Q262 405 221 352Q191 313 171 233T151 117Q151 38 213 38Q269 38 323 108L331 118L384 328Z"></path><path stroke-width="1" id="E9-MJMATHI-4E" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E9-MJMAIN-32" x="0" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E9-MJMATHI-6C" x="500" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E9-MJMATHI-67" x="799" y="0"></use><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#E9-MJMATHI-4E" x="1279" y="0"></use></g></svg></span><script type="math/tex" id="MathJax-Element-9">2lgN</script>，接近平衡。在插入或删除操作时，要使用左右旋以保证其满足红黑树性质。</li><li>ConcurrentHashMap：与HashMap不同的是，ConcurrentHashMap是线程安全的，为分段结构，segment中含有Hashtable，每次对一个segment加锁进行put、delete等操作，而不是锁整张表，segment、的默认多少仍然是16，意味着可以有16个线程同时操作该ConcurrentHashMap。1.8对ConcurrentHashMap进行了改进，抛弃了之前臃肿的segment数组，改用node + CAS + sychronized + 红黑树来实现。采用对数组元素进行加锁，从而实现了更细粒度的锁。</li><li>CopyOnWriteList （写时复制List）其发布了一个事实上不可变的对象，由于不可变，允许多个线程访问该容器，每当修改容器时，都要创建一个副本进行修改然后再发布。所以最好在迭代访问操作远远多于修改操作的时候才使用该同步容器。</li><li>BlockingQueue</li></ul><h3><a name='header-n54' class='md-header-anchor '></a>HashMap多线程下出现的问题</h3><ul><li>put的覆盖问题：存在两个线程添加一个元素，entry相同，由于e.next不同步，在拉链时出现覆盖问题。</li><li>put之后导致get无限循环：发生在扩容中，当一个线程被挂起时，另一线程重组链表后可能发生循环访问的问题。<a href='https://yq.aliyun.com/articles/38431'>记不清可见</a></li></ul><h3><a name='header-n62' class='md-header-anchor '></a>ConcurrentHashMap 如何扩容？</h3><h2><a name='header-n63' class='md-header-anchor '></a>Java NIO</h2><p>最主要的三个类是Buffer，Channel和Selector。与传统的IO比较主要有亮点不同。</p><ul><li>IO是面向流的，而NIO是面向缓冲区的。传统的IO面向流意味着每次从流中读取一个或者多个字节，这些数据没有缓冲在任何一个地方。如果要前后移动流中的数据，要先将其还存在一个缓冲区中。而面向缓冲区的NIO有先天的前后操纵数据的优势。</li><li>IO是阻塞的，即是，当调用read()或者write()方法时，当没有数据读出或者没有数据写入时，线程将是阻塞的；不同的是NIO是非阻塞的，当一个线程发送读的请求时，其只能读取当前可返回的数据，如果当前没有可用的数据，就什么都不会返回。写请求时，不用等到所写的数据要全部写入时，线程就可以去做其他的事情。线程通常将非阻塞的IO用于在其他的通道上进行读写操作，所以一个IO可以管理多个通道。</li></ul><h3><a name='header-n73' class='md-header-anchor '></a>Buffer</h3><p>每种类型都有对应的Buffer，但是常用的Buffer为<code>ByteBuffer</code>和<code>CharBuffer</code>。<code>Buffer</code>具体的实例由<code>XXXBuffer.allocate(int capacity)</code>来获取。<code>ByteBuffe</code>还有一个子类<code>MappedByteBuffer</code>，这个子类通常通过<code>Channel</code>的<code>map()</code>方法返回，该缓冲区将磁盘的全部或部分内容映射到内存(<strong>虚拟内存</strong>)。读写性能较高。</p><p>其有几个比较重要的标志，capacity，limit和position。其中capacity是指缓冲区的容量，由allocate初始化的时候指定。limit是指读取和写入时的上界限，position是指读取和写入时下一个位置。读取之前，调用<code>flip()</code>使position回到0 (读取的下一位置)，limit回到定位到最后一个元素的下一位置 (读取的上界限)，capacity不变。写入时，首先调用<code>clear()</code>方法，此时缓冲区中的元素<strong>并没有真正被clear</strong>，使用<code>buffer.get(int pos)</code>仍然能获取到缓冲区的内容，只是将position定位到0，将limit定位到capacity的位置，写入时，将覆盖原缓冲区的内容。</p><h3><a name='header-n78' class='md-header-anchor '></a>Channel</h3><p>一般需要用流的<code>getChannel()</code>方法来初始化Channel，例如<code>new FileInputStream(f).getChannel()</code>，<code>new FileOutputStream(f).getChannel()</code>，<code>new RandomAccessFile(f,&quot;rw&quot;).getChannel()</code>。读取文件到Buffer里可以用<code>channel</code>的<code>read()</code>方法或<code>channel</code>的<code>map(***)</code>方法，写入则使用<code>channel</code>的<code>write()</code>方法。</p><p>使用<code>read()</code>的具体形式为</p><pre class="md-fences md-end-block" lang="java"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;">...;</span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-variable">File</span> <span class="cm-variable">f</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">File</span>(<span class="cm-string">"afile.txt"</span>);</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-variable">FileChannel</span> <span class="cm-variable">channel</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">FileInputStream</span>(<span class="cm-variable">f</span>).<span class="cm-variable">getChannel</span>();</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-variable">ByteBuffer</span> <span class="cm-variable">buffer</span> <span class="cm-operator">=</span> <span class="cm-variable">ByteBuffer</span>.<span class="cm-variable">allocate</span>(<span class="cm-variable">f</span>.<span class="cm-variable">length</span>());</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-variable">channel</span>.<span class="cm-variable">read</span>(<span class="cm-variable">buffer</span>);</span></pre><pre class=""><span style="padding-right: 0.1px;">...;</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 102px;"></div></div></div></pre><p>使用<code>map()</code>的具体形式为</p><pre class="md-fences md-end-block" lang="java"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;">...;</span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-variable">File</span> <span class="cm-variable">f</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">File</span>(<span class="cm-string">"afile.txt"</span>);</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-variable">FileChannel</span> <span class="cm-variable">channel</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">FileInputStream</span>(<span class="cm-variable">f</span>).<span class="cm-variable">getChannel</span>();</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-variable">MappedByteBuffer</span> <span class="cm-variable">buffer</span> <span class="cm-operator">=</span> <span class="cm-variable">channel</span>.<span class="cm-variable">map</span>(<span class="cm-variable">FileChannel</span>.<span class="cm-variable">MapMode</span>.<span class="cm-variable">READ_ONLY</span>, <span class="cm-number">0</span>, <span class="cm-variable">f</span>.<span class="cm-variable">length</span>());</span></pre><pre class=""><span style="padding-right: 0.1px;">...;</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 85px;"></div></div></div></pre><h3><a name='header-n87' class='md-header-anchor '></a>Selector</h3><p>selector使用单线程处理多个channel，当应用打开了多个channel且每个channel的吞吐量不是很大时，使用channel就比较方便。使用selector分如下的几步：</p><ul><li><p>创建：使用<code>Selector selector = Selector.open()</code></p></li><li><p>将channel注册到selector：<code>channel.register(selector, **)</code>，该方法可返回一个SelectorKey，代表该channel在selector中的&quot;代号&quot;。与selector一起使用时，channel一定处于非阻塞模式下。所以需要提前设置<code>channel.configureBlocking(false)</code>。</p></li><li><p>使用selector几个select的重载方法测试通道有多少已经准备好了：</p><ul><li>int select()阻塞到至少有一个对象在通道上准备好了。</li><li>int select(long timeout)最长会阻塞timeout毫秒</li><li>int selectNow()不会阻塞，不管什么情况会直接返回，如果自上次调用选择操作以来，没有就绪的通道则直接返回0。</li></ul></li><li><p>调用select方法之后，如果有返回值，则说明已经有selector就绪了。此时可以通过selectedKey来选择已选择键集中就绪的通道。使用<code>Set&lt;SelectionKey&gt; selectedKey = selector.selectedKeys();</code>，之后在得到的SelectionKey的Set中可以通过SelectionKey提供的方法来操作channel。得到Channel的基本方法为<code>selectionKey.channel()</code> 。</p></li></ul><h2><a name='header-n113' class='md-header-anchor '></a>SpringMVC和MyBatis</h2><h3><a name='header-n114' class='md-header-anchor '></a>SpringMVC</h3><h4><a name='header-n115' class='md-header-anchor '></a>运行流程</h4><p>用户向服务端发送请求，被DispatcherServlet (调度员Servlet)截获，然后交由HandlerMapping处理，获得Handler对象及其对应的拦截器，以HandlerExecutionChain返回给DispatcherServlet，DispatcherServlet根据返回的Handler选择合适的HandlerAdapter处理，该适配器调用对应Handler的实际处理请求的方法（例如login）。接下来执行相应的Handler方法，并返回一个ModelAndView对象，这个对象中包含视图名称和数据对象，选择一个合适的ViewResolver对象返回给DispatcherServlet，渲染View并返回给客户端。</p><h3><a name='header-n118' class='md-header-anchor '></a>MyBatis</h3><h4><a name='header-n119' class='md-header-anchor '></a>简介</h4><p>主要是把sql语句和代码分开，以增强项目的可维护性。一般将sql写在xml文件中，被叫做mapper文件，一个BEAN对应一个mapper文件，其中有对该BEAN的增删改查。涉及了两个比较重要的类，SqlSessionFactory和SqlSession。其中增删改查的方法均源于SqlSession。也可以使用Mapper接口的<strong>动态代理</strong>对象来访问数据库，invoke方法中只根据package+Mapper+method全限定名确定执行的方法，即一个mapper文件对应一个Mapper接口，接口的一个方法对应了一个sql语句。方法实际上底层仍然调用的是SqlSession的方法。</p><h4><a name='header-n122' class='md-header-anchor '></a>动态代理</h4><p>为了增强target，代理类需要继承一个InvocationHandler接口，实现invoke方法。以<code>Proxy.newProxyInstance(ClassLoader, Class(Interface), InovationHandler)</code>获取代理对象。只能为接口对象获取代理。MyBatis的Mapper接口因为没有实现类，因此<strong>直接运行代理方法而没有对所谓的target增强。</strong> </p><h4><a name='header-n125' class='md-header-anchor '></a>常用标签</h4><ul><li>首先是config文件中的标签：根标签为<code>&lt;configuration&gt;</code>，其中较为重要的标签为<code>&lt;settings&gt;</code>：设置mybatis的行为，制指定日志实现、缓存、懒加载等等。<code>&lt;environments&gt;</code>配置mybatis的环境变量，即为数据源配置。需要配置dataSource和事务管理器等。<code>&lt;typeAliases&gt;</code>指定类型的别名，为其设置一个方便的名字。<code>&lt;mappers&gt;</code>标签指定了每张数据表所属于的mapper映射器。</li><li>Mapper XML文件中的标签：增(add)，删(delete), 改(update), 查(select)。<code>&lt;resultMap&gt;</code>是mybatis中比较强大的标签，可以将数据库中选择的column(column属性)指定成需要的对象属性(property)，在关联映射中这个属性用的尤其多。关联其他表的一行记录时，在<code>resultMap</code> 中使用<code>&lt;association&gt;</code> 标签，用<code>column</code> 指定对应的外键，<code>select</code>指定定义好的查询，<code>javaType</code> 指定返回的类型。关联其他表的多行记录时，用<code>&lt;collection&gt;</code> 标签，除上面的属性可以指定外，还可以使用<code>fetchType=&quot;lazy&quot;</code> 指定查询模式为懒加载。</li></ul><h4><a name='header-n133' class='md-header-anchor '></a>动态SQL</h4><p>为适应实际开发中经常碰到的拼接sql的情况，常使用MyBatis提供了一些标签提供对动态sql的支持。if用来判断条件，choose配合when、otherwise用来判断多个条件，where可以拼接后面的where条件而不需要加<code>where 1=1</code> 这种语句，set可用在更新语句中，foreach可用于<code>where xx in</code> 的查询语句；bind可以从OGNL表达式中创建一个变量并将其绑定到上下文。</p><h4><a name='header-n136' class='md-header-anchor '></a>事务支持和缓存机制</h4><p>MyBatis通过TransactionFactory来返回事务管理对象。其中JdbcTransaction直接使用JDBC的提交和回滚事务管理机制。（java.sql.Connection中的commit()和rollback()来实现。）ManagedTransaction的事务管理交给容器管理。</p><p>MyBatis有两级缓存机制。</p><ul><li><p>SqlSession级别，构造SqlSession的时候使用HashMap用于存储缓存数据，不同的SqlSession存储的缓存数据之间是不影响的。同一个SqlSession对象执行两次相同的查询操作，第二次可以直接从内存中拿数据而不需要再次查表。如果SqlSession执行了DML操作并提交到了数据库，MyBatis将会清空当前的缓存，避免脏读。MySql默认开启。</p></li><li><p>mapper级别，多个SqlSession使用同一个Mapper的查询操作，得到的数据会缓存在二级缓存区域，同样使用HashMap进行数据存储。但是缓存是多个SqlSession共享的，作用域是mapper的同一个namespace。不同的SqlSession执行两次相同的namespace下的sql语句，第二次执行的可以直接额从内存中拿数据。默认没有开启，需要在setting参数中配置开启二级缓存。使用如下配置：</p><pre class="md-fences md-end-block" lang="xml"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tag cm-bracket">&lt;</span><span class="cm-tag">settings</span><span class="cm-tag cm-bracket">&gt;</span></span></pre></div><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-tag cm-bracket">&lt;</span><span class="cm-tag">setting</span> <span class="cm-attribute">name</span>=<span class="cm-string">"cacheEnable"</span> <span class="cm-attribute">value</span>=<span class="cm-string">"true"</span><span class="cm-tag cm-bracket">/&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tag cm-bracket">&lt;/</span><span class="cm-tag">settings</span><span class="cm-tag cm-bracket">&gt;</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 51px;"></div></div></div></pre><p>在mapper.xml中可以配置二级缓存的属性。eviction收回策略LRU、FIFO、SOFT、WEAK；size：缓存大小；flushInterval刷新间隔，默认没有；readOnly：读写属性，默认false。</p></li></ul><h2><a name='header-n151' class='md-header-anchor '></a>垃圾回收机制</h2><p>主要分新生代和老年代的垃圾回收。新生代采用复制算法，即一块较大的Eden（[&#39;i:dən]）区域和两块较小的survivor区域，对象优先在Eden区域中分配，当Eden区域满了，进行一次复制回收，因为java对象大部分的对象都具有朝生夕灭的特点，所以survivor区域很小（Minor GC）；老年代采用标记整理算法，即将还在使用的对象移到一边，以在回收的同时产生连续的空间。（Full GC） <br/>
什么对象可以被回收？ <br/></p><ul><li>引用计数法：每有一个对象被引用，就将该对象的引用计数加一，引用失效时，就将引用计数减一，当引用计数为0的时候，表明该对象可以被回收。但是难以解决对象循环引用的问题。</li><li>可达性分析算法：通过一系列“GC Root”的对象作为起始点，从这个节点向下搜索引用该节点的对象，一条路径称为一条引用链，如果一个对象到GC Root没有任何可达的引用链，则该对象就是可以被GC的。可作为GC Root的对象包括（1）虚拟机栈中引用的对象（2）方法区中类静态属性引用的对象（3）方法区中引用的常量（4）Native方法引用的对象。 <br/>
几条原则： <br/></li><li>对象优先在Eden区分配</li><li>大对象直接进入老年代：大对象指需要连续大块内存的java对象，例如很长的字符串和很大的数组（写程序应该避免使用朝生夕灭的短命大对象）；由于申请不到连续的足够空间，即使内存区域还含有很多空闲区域，仍然需要进行垃圾回收以获取足够的连续空间来安置他们。所以大对象直接进入老年代可以避免较为频繁的GC。</li><li>长期存活的对象进入老年代：对象的年龄计数器Age，每熬过一次Minor GC，则该对象的年龄就增加一岁。默认大于15岁的对象进入老年代。动态对象年龄判断：相同年龄的对象大小的总和大于Survivor空间的一半，年龄大于等于该年龄的对象可以直接进入老年代。</li></ul><p>空间分配担保（Minor GC 和 Full GC）：在Minor GC之前，会先检查老年代最大可用连续空间是否大于新生代所有对象空间，Minor GC就是安全的。如果不成立，会检查是否允许担保失败，如果允许，就检查连续空间是否大于历次晋升到老年代的对象的大小的平均值，如果是，就进行一次Minor GC，同时风险是老年代已经存不下了，这时就要再进行一次Full GC，否则进行一次Full GC。如果不允许担保失败，就要在Minor GC前先进行Full GC。</p><h2><a name='header-n174' class='md-header-anchor '></a>类加载机制</h2><ul><li>双亲委派模型及其意义：启动类加载器（Bootstrap ClassLoader）在最顶层，接着是扩展类加载器（Extension ClassLoader）和应用程序类加载器（Application ClassLoader），最底层是用户定义的类加载器。双亲委派模型要求在有类加载任务的时候首先检查父类加载器是否可以加载该类，每一个类的加载都要首先传送到顶层的启动类加载器。当父类加载器不能完成加载时，才进行子类加载器的加载。这样做的意义在于类加载器具有了优先级关系。例如Object类在启动类加载器中加载，无论哪个类加载器加载，最终都交由启动类加载器加载，因此Object类在各种类加载器情况下都是同一个类。如果不采取这种模型，将产生多个同名但不同的类，java的基础运行得不到保障。在当前JDK下，用户自定义与rt.jar中类库重名的类是无法被加载运行的。</li></ul><h2><a name='header-n179' class='md-header-anchor '></a>多线程，并发</h2><h3><a name='header-n180' class='md-header-anchor '></a>volatile</h3><p>只保证可见性，保证在更新之后将变量写到其他的线程可见的地方，我的理解是写到主内存而不是每个线程的工作内存。在读取的时候也是从主内存而不是自己的私有拷贝中读取值。但是不保证原子性，不保证线程安全，自增操作就是不安全的，因为自增操作依赖于当前的值，具有取值-改值-写入的特性，改值和写入是原子的，但取值不是原子的，在取值的过程中可能被其他线程改动。</p><h3><a name='header-n183' class='md-header-anchor '></a>信号量 (Semaphore) [&#39;seməfɔː]</h3><p>控制多线程情况下某个资源能被访问的次数。通过acquire()获取一个许可，如果没有就等待，通过release()释放一个信号。如果设置信号量的个数为1，则可以当作互斥锁使用</p><h3><a name='header-n186' class='md-header-anchor '></a>AtomicInteger</h3><p>提供了一些原子的操作，例如CAS，incrementAndGet；CAS是指比较当前的变量值与期望的变量值，如果相等才进行赋值新值的操作。例如在incrementAndGet中就是在一个无限循环中不停的与期望值比较，相等了才Set新的值；有Bug，ABA问题，智能保证得到的值与期望值相等，不能知道其在检查的过程中有没有改变。J.U.C 提供了一个AtomicStampedReference来解决这个问题，如名称，邮戳，通过控制变量版本来保证CAS的正确性。</p><h3><a name='header-n189' class='md-header-anchor '></a>ThreadLocal</h3><p>维持线程封闭的一种方法，每个线程拥有一个属于自己的副本，其get方法返回的值总是当前线程中调用其set方法设置的值。这些用于特定线程的值保存在Thread对象中。例如多线程数据库的Connection连接。</p><h3><a name='header-n192' class='md-header-anchor '></a>Future</h3><p>配合Callable使用获取多线程call方法返回的结果，当其调用get方法时，get将是阻塞的，直到callable线程返回了结果；在get方法之前可以进行其它的动作。FutureTask实现了Runnable和Future两个接口，可以提交给ExecutorService，也可以提交给Thread。</p><h3><a name='header-n195' class='md-header-anchor '></a>final 域</h3><p>用于构造不可变对象，但在多线程的语义中，final能确保初始化过程的安全性，内存的可见性，从而可以不受限制的访问不可变对象，共享这些对象时无需同步。</p><h3><a name='header-n198' class='md-header-anchor '></a>获取线程dump文件</h3><p>Thread类提供了一个getStackTrace()方法也可以用于获取线程堆栈。</p><h3><a name='header-n201' class='md-header-anchor '></a>线程的唤醒与阻塞</h3><ul><li>yield：Thread的方法，让步，放弃CPU时间到等待运行状态（而不是阻塞状态），如果有优先级较高的线程则运行优先级高的线程，否则仍然运行被让步的线程。</li><li>sleep：Thread方法，睡眠，放弃CPU时间到阻塞状态，阻塞指定的时间，但是不放弃对象锁，允许较低优先级的线程获取机会。</li><li>join：Thread方法，加入，主线程要等待该线程执行完毕才能进行join()方法之后的调用</li><li>wait/notify/notifyAll：Object方法，等待/唤醒/唤醒所有；假如一个obj调用了这组方法，必须配合sychronized(obj)使用，在同步块中。调用了这组方法，将释放同步块拿到的obj的锁。调用wait()不加参数的方法将一直等待，直到收到了notify的信号才继续执行。</li></ul><h3><a name='header-n215' class='md-header-anchor '></a>线程池</h3><h4><a name='header-n216' class='md-header-anchor '></a>简介</h4><p>将任务的执行和任务的提交解耦开来。避免为一个任务开启和销毁线程所做的开销。Executors工厂类新建ExecutorService对象，该对象用submit方法提交线程对象。</p><h4><a name='header-n219' class='md-header-anchor '></a>如果你提交任务时，线程池队列已满，这时会发生什么</h4><ul><li>如果队列满了，而且此时运行的数量小于maximumPoolSize，则仍然创建新的线程运行任务。（一般情况下运行的线程数为corePoolSize）。如果队列已满而且线程数也到达maximumPoolSize，则抛出异常（RejectedExecutionException）。</li><li>以上情况针对于<code>ArrayBlockingQueue&lt;Runnable&gt;</code>，如果是<code>LinkedBlockingQueue&lt;Runnable&gt;</code>，因为该队列无大小限制，所以不存在上述问题。</li></ul><h3><a name='header-n227' class='md-header-anchor '></a>几种锁</h3><ul><li><p>ReentrantLock：可重入锁，功能与sychronized相当（sychronized）也是可重入的，必须要在finally块中释放锁，因此sychronized较为安全，而且sychronized是基于JVM的，lock是基于JDK的。相比于sychronized，实现了几个高级功能</p><ol start='' ><li>等待可中断：当持有线程请求的锁的线程长时间不释放锁时，可以选择放弃等待锁。<code>tryLock(long timeout, Unit unit)</code>。</li><li>公平锁：sychronized和ReentrantLock在默认情况下实现的都是非公平锁，即：当一个线程请求锁时，这个锁正好是可用的，不必理会其它请求该锁的线程而直接占用该锁，使用new RenentrantLock(boolean fair)来创建公平锁。虽然说公平，但是公平锁的吞吐量较低，因为每次锁释放时，将队列头的线程唤醒到就绪状态是比较消耗资源的。非公平锁的插队抢占方式带来了吞吐量的提升</li></ol></li></ul><p>ReentrantReadWriteLock</p><h3><a name='header-n241' class='md-header-anchor '></a>如何在两个线程之间共享数据</h3><p>利用共享对象共享数据，wait/notify/notifyAll、await/signal/signalAll进行唤起和等待。如果两个线程的动作相同，可以在线程类内部创建该共享数据，如果两个线程动作不同，可以将共享数据另外封装成一个对象，并且对该对象进行共享操作。</p><h2><a name='header-n244' class='md-header-anchor '></a>http 和 https</h2><ul><li>http：建立连接（DNS）--&gt; 发送请求 --&gt; 响应请求 --&gt; 关闭连接</li><li>https：请求建立连接 --&gt; 服务端发送证书（包括公钥）给客户端 --&gt; 协商加密等级 --&gt; 客户端根据加密等级将会话密钥利用公钥进行加密--&gt; 服务端利用私钥解密会话密钥并利用会话密钥加密通信的信息。</li></ul><h2><a name='header-n252' class='md-header-anchor '></a>数据库</h2><h3><a name='header-n253' class='md-header-anchor '></a>mysql为什么用B+树</h3><p>B+树为了存储索引，索引一般数据量比较大，存储在磁盘上。一次读取磁盘I/O的时间比较大，所以要求I/O次数要小。B-树由于中间节点存储了数据，每个节点数据量就比较大，而每次I/O读出数据是一定的，所以B-树的读取次数就比较多。而B+树中间节点是不存储数据的，因此I/O次数较少。同时由于只在叶子节点存储数据，树高不会有太大差别，所以每次查找效率相当，查找比较稳定。</p><h3><a name='header-n256' class='md-header-anchor '></a>数据库事务的四种隔离级别</h3><ul><li>未提交读（Read Uncommitted）：在事务没有提交时就允许读取数据。允许其他事务读取没有提交的数据。<strong>脏读</strong></li><li>提交读（Read Committed）：只能读取已经提交的数据。解决了脏读问题。Oracle等多数数据库默认都是该级别 。但有一个问题：<strong>不可重复读</strong> 。在一个事务里，有多次读取操作，但是在两次读取之间有其他的事务改变了数据，此时导致两次读取的数据不同。</li><li>可重复读（Repeatable Read）：可重复读，在同一事务内，查询的数据始终与事务开始时是一致的。InnoDB的默认级别，消除了不可重复读，但是存在<strong>幻读</strong>现象。<strong>幻读</strong>是指一个事务对表进行操作，改动涉及了表中的所有数据。同时第二个事务向表中插入一行新的数据，此时操作第一个数据的用户就会发现数据表中还有没有修改的数据，好像产生了幻觉一样。</li><li>可串行化（Serializable）：完全串行化的读，每次读都要获得表级别的锁，读写都会相互阻塞。</li></ul><h3><a name='header-n270' class='md-header-anchor '></a>ACID事务</h3><ul><li>A（Atomicity 原子性）：一个事务要么执行，要么不执行。</li><li>C（Consistency 一致性）：事务的运行不改变数据的一致性，例如，完整性约束了a+b=10，事务改变了a，b也随之改变。</li><li>I（Isolation独立性）：事务之间不会交替执行。</li><li>D（Durability持久性）：改变的数据持久的留在数据库中。</li></ul><h3><a name='header-n284' class='md-header-anchor '></a>InnoDB和MyISAM</h3><h4><a name='header-n285' class='md-header-anchor '></a>InnoDB</h4><p>支持了ACID事务，提供了数据库的四种完整性约束，提供了行级锁和完整性约束，MySQL在运行InnoDB的引擎时，会在内存中建立缓冲池，用于缓冲数据和索引，其设计目标是处理较大数量的数据。当要使用数据库事务时，该引擎时首选，因为支持更小粒度的锁，写操作不会锁整张表，适合并发较高时提升效率。但是该引擎没有保存行数，<code>select count(*)from table</code> 需要扫面整张表。</p><p></p><p>其索引结构为B+树，索引文件本身就是数据文件，即B+树数据域存储的本身就是data数据，索引的key就是数据表的主键，因此InnoDB数据表本身就是<strong>主索引</strong> 。一个主索引的例子如图所示：</p><p><img src='http://images2015.cnblogs.com/blog/731178/201603/731178-20160320205622193-1852020506.jpg' alt='InnoDB索引示意图' /></p><p>对于<strong>辅助索引</strong> 来说，B+树数据域存储的是主键的值，如下图所示</p><p><img src='http://images2015.cnblogs.com/blog/731178/201603/731178-20160320205632724-1223368895.jpg' alt='image' /></p><p>这种基于主键的聚集索引使得按主键查询效率较高，但是对于辅助索引来说，需要查询两次，首先需要查询到主键，然后通过主键查询数据。这种在索引中直接存储数据的索引方式成为<strong>聚簇索引</strong> 。</p><h4><a name='header-n300' class='md-header-anchor '></a>MyISAM</h4><p>没有提供对数据库事务的支持，也不支持行级锁和外键。每次对表进行事务操作时需要锁整张表，效率较低。但存储了数据记录的行数。如果数据库的读操作远远多于写操作且不需要数据库事务的支持，那么MyISAM也是一种好的选择。</p><p></p><p>其索引结构同样是B+树，但不同于InnoDB的是，B+树中存储的是实际数据的地址，地址指向了实际数据。以下两张图分别给出了<strong>主索引</strong> 和 <strong>辅助索引</strong> 的例子。</p><p><img src='http://images2015.cnblogs.com/blog/731178/201603/731178-20160320204001959-1320607047.png' alt='image' /></p><p><img src='http://images2015.cnblogs.com/blog/731178/201603/731178-20160320204143084-1395279894.png' alt='image' /></p><h4><a name='header-n311' class='md-header-anchor '></a>比较和讨论</h4><p>大尺寸的数据趋向于选择InnoDB，因为其支持事务处理和故障恢复。数据库的大小决定了恢复的长短，InnoDB可以利用事务日志进行数据恢复，这会比较快。主键查询在InnoDB也会相当快。大批的INSERT语句(在每个INSERT语句中写入多行，批量插入)在MyISAM下会快一些，但是UPDATE语句在InnoDB下则会更快一些，尤其是在并发量大的时候。</p><p>了解数据库底层原理对我们正确使用和优化数据库都有好处，比如：</p><ul><li>由于InnoDB直接存储主键数据作为索引，所以不宜用过长的主键来作为主键，因为这会增加索引的数据大小，过长的主索引大小会令辅助索引变得过大。</li><li>使用非单调的字段作为主键不是一个好主意，这可能会使索引为了维持B+树的特性而不停的分裂调整，十分低效。推荐使用递增的数据列作为主键。</li></ul><h2><a name='header-n323' class='md-header-anchor '></a>设计模式</h2><h3><a name='header-n324' class='md-header-anchor '></a>几种单例模式</h3><ul><li><p>懒汉模式  <br/></p><pre class="md-fences md-end-block" lang="java"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">public</span> <span class="cm-keyword">class</span> <span class="cm-def">SingletonInstance</span>{</span></pre></div><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">private</span> <span class="cm-variable">SingletonInstance</span> <span class="cm-variable">instance</span> ;</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">private</span> <span class="cm-variable">SingletonInstance</span>(){};</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">public</span> <span class="cm-keyword">static</span> <span class="cm-variable">SingletonInstance</span> <span class="cm-variable">getInstance</span>(){</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">if</span>(<span class="cm-variable">instance</span> <span class="cm-operator">==</span> <span class="cm-atom">null</span>)</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-tab">    </span><span class="cm-variable">instance</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">SingletonInstance</span>();</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">return</span> <span class="cm-variable">instance</span> ;</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 153px;"></div></div></div></pre><p>这种情况下使用了lazy loading，但是是线程不安全的，可以对getInstance方法进行sychronized关键字包装实现同步，但是这样就损失了效率</p></li><li><p>饿汉模式</p><pre class="md-fences md-end-block" lang="java"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">public</span> <span class="cm-keyword">class</span> <span class="cm-def">SingletonInstance</span>{</span></pre></div><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">private</span> <span class="cm-keyword">static</span> <span class="cm-variable">SingletonInatance</span> <span class="cm-variable">instance</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">SingletonInstance</span>();</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">private</span> <span class="cm-variable">SingletonInstance</span>();</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">public</span> <span class="cm-keyword">static</span> <span class="cm-variable">SingletonInstance</span> <span class="cm-variable">getInstance</span>(){</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">return</span> <span class="cm-variable">instance</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 119px;"></div></div></div></pre><p>这种情况下基于classLoader方式规避了线程安全问题，但是类的装载有很多种可能，不能保证一定是调用getInstance导致了类的装载，所以没有达到lazy loading的效果，可能浪费资源。</p></li><li><p>内部类方式</p><pre class="md-fences md-end-block" lang="java"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">public</span> <span class="cm-keyword">class</span> <span class="cm-def">SingletonInstance</span>{</span></pre></div><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">private</span> <span class="cm-keyword">static</span> <span class="cm-keyword">class</span> <span class="cm-def">SingletonHolder</span>{</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">private</span> <span class="cm-keyword">static</span> <span class="cm-keyword">final</span> <span class="cm-variable">SingletonInstance</span> <span class="cm-variable">INSTANCE</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">SingletonInstance</span>();</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">private</span> <span class="cm-variable">SingletonInstance</span>(){};</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">public</span> <span class="cm-keyword">static</span> <span class="cm-variable">getInstance</span>(){</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">return</span> <span class="cm-variable">SingletonHolder</span>.<span class="cm-variable">INSTANCE</span> ;</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 153px;"></div></div></div></pre><p>这种方式只在调用getInstance的时候才进行对SingletonInstance的实例化，比饿汉模式更加合理。</p></li></ul></div>
</body>
</html>